home *** CD-ROM | disk | FTP | other *** search
- #include "lib.h"
- #include <sys/types.h>
- #include <time.h>
- #include <stdio.h>
-
- #define toint(X) (X - '0')
-
-
- static char timebuf[26];
-
- static char *day[] =
- {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
- static char *month[] =
- {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
- void tzset();
-
- char *asctime(time)
- register _CONST struct tm *time;
- /*
- * Convert <time> structure value to a string. The same format, and
- * the same internal buffer, as for ctime() is used for this function.
- */
- {
- if (time == NULL)
- strcpy(timebuf, "??? ??? ?? ??:??:?? ????\n");
- else
- sprintf(timebuf, "%.3s %.3s%3d %02d:%02d:%02d %04d\n",
- day[time->tm_wday], month[time->tm_mon], time->tm_mday,
- time->tm_hour, time->tm_min, time->tm_sec, 1900+time->tm_year);
- return(timebuf);
- }
-
- char *ctime(rawtime)
- _CONST time_t *rawtime;
- /*
- * Convert <rawtime> to a string. A 26 character fixed field string
- * is created from the raw time value. The following is an example
- * of what this string might look like:
- * "Wed Jul 08 18:43:07 1987\n\0"
- * A 24-hour clock is used, and due to a limitation in the ST system
- * clock value, only a resolution of 2 seconds is possible. A pointer
- * to the formatted string, which is held in an internal buffer, is
- * returned.
- */
- {
- return(asctime(localtime(rawtime)));
- }
-
- /* mktime, localtime, gmtime */
- /* written by ERS and placed in the public domain */
-
- #include <ctype.h>
-
- #define SECS_PER_MIN (60L)
- #define SECS_PER_HOUR (60*SECS_PER_MIN)
- #define SECS_PER_DAY (24*SECS_PER_HOUR)
- #define SECS_PER_YEAR (365*SECS_PER_DAY)
- #define SECS_PER_LEAPYEAR (SECS_PER_DAY + SECS_PER_YEAR)
-
- static
- int days_per_mth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-
- static time_t tzoffset();
- static int indst();
-
- time_t timezone = -1; /* holds # seconds west of GMT */
- static int dst = -1; /* whether dst holds in current timezone */
-
- /*
- * FIXME: none of these routines is very efficient. Also, none of them
- * handle dates before Jan 1, 1970.
- *
- */
-
- /*
- * mktime: take a time structure representing the local time (such as is
- * returned by localtime() and convert it into the standard representation
- * (as seconds since midnight Jan. 1 1970, GMT).
- *
- */
-
- time_t
- mktime(t)
- _CONST struct tm *t;
- {
- time_t s;
- int y;
-
- y = t->tm_year - 70;
- if (y < 0) /* year before 1970 */
- return (time_t) -1;
- s = (SECS_PER_YEAR * y) + ( ((y+1)/4) * SECS_PER_DAY);
- /* extra days for leap years */
- if ( (y+2)%4 )
- days_per_mth[1] = 28;
- else
- days_per_mth[1] = 29;
-
- for (y = 0; y < t->tm_mon; y++)
- s += SECS_PER_DAY * days_per_mth[y];
-
- s += (t->tm_mday - 1) * SECS_PER_DAY;
- s += t->tm_hour * SECS_PER_HOUR;
- s += t->tm_min * SECS_PER_MIN;
- s += t->tm_sec;
-
- /* Now adjust for the time zone and possible daylight savings time */
- if (timezone == -1)
- tzset();
- s += timezone;
- if (dst == 1 && indst(t))
- s -= SECS_PER_HOUR;
-
- return s;
- }
-
-
- static struct tm the_time;
-
- struct tm *gmtime(t)
- _CONST time_t *t;
- {
- struct tm *stm = &the_time;
- time_t time = *t;
- int year, mday, i;
-
- if (time < 0) /* negative times are bad */
- return 0;
- stm->tm_wday = ((time/SECS_PER_DAY) + 4) % 7;
-
- year = 70;
- for (;;) {
- if (time < SECS_PER_YEAR) break;
- if ((year % 4) == 0) {
- if (time < SECS_PER_LEAPYEAR)
- break;
- else
- time -= SECS_PER_LEAPYEAR;
- }
- else
- time -= SECS_PER_YEAR;
- year++;
- }
- stm->tm_year = year;
- mday = stm->tm_yday = time/SECS_PER_DAY;
- days_per_mth[1] = (year % 4) ? 28 : 29;
- for (i = 0; mday >= days_per_mth[i]; i++)
- mday -= days_per_mth[i];
- stm->tm_mon = i;
- stm->tm_mday = mday + 1;
- time = time % SECS_PER_DAY;
- stm->tm_hour = time/SECS_PER_HOUR;
- time = time % SECS_PER_HOUR;
- stm->tm_min = time/SECS_PER_MIN;
- stm->tm_sec = time % SECS_PER_MIN;
- stm->tm_isdst = 0;
-
- return stm;
- }
-
- /* given a standard time, convert it to a local time */
-
- struct tm *localtime(t)
- _CONST time_t *t;
- {
- struct tm *stm;
- time_t offset; /* seconds between local time and GMT */
-
- if (timezone == -1) tzset();
- offset = *t - timezone;
- stm = gmtime(&offset);
- if (stm == NULL) return stm; /* check for illegal time */
- stm->tm_isdst = (dst == -1) ? -1 : 0;
-
- if (dst == 1 && indst(stm)) { /* daylight savings time in effect */
- stm->tm_isdst = 1;
- if (++stm->tm_hour > 23) {
- stm->tm_hour -= 24;
- stm->tm_wday = (stm->tm_wday + 1) % 7;
- stm->tm_yday++;
- stm->tm_mday++;
- if (stm->tm_mday > days_per_mth[stm->tm_mon]) {
- stm->tm_mday = 1;
- stm->tm_mon++;
- }
- }
- }
- return stm;
- }
-
- /* set the timezone and dst flag to the local rules */
- void
- tzset()
- {
- timezone = tzoffset(getenv("TZ"), &dst);
- }
-
- /*
- * determine the difference, in seconds, between the given time zone
- * and Greenwich Mean. As a side effect, the integer pointed to
- * by hasdst is set to 1 if the given time zone follows daylight
- * savings time, 0 if there is no DST.
- *
- * Time zones are given as strings of the form
- * "[TZNAME][h][:m][TZDSTNAME]" where h:m gives the hours:minutes
- * east of GMT for the timezone (if [:m] does not appear, 0 is assumed).
- * If the final field, TZDSTNAME, appears, then the time zone follows
- * daylight savings time.
- *
- * Example: EST5EDT would represent the N. American Eastern time zone
- * CST6CDT would represent the N. American Central time zone
- * NFLD3:30NFLD would represent Newfoundland time (one and a
- * half hours ahead of Eastern).
- * OZCST-9:30 would represent the Australian central time zone.
- * (which, so I hear, doesn't have DST).
- *
- * NOTE: support for daylight savings time is currently very bogus.
- * It's probably best to do without, unless you live in North America.
- *
- */
- static
- time_t tzoffset(s, hasdst)
- char *s;
- int *hasdst;
- {
- time_t off = 0;
- int x, sgn = 1;
-
- *hasdst = -1; /* Assume unknown */
- if (!s || !*s)
- return 0; /* Assume GMT */
- *hasdst = 0;
-
- while (isalpha(*s)) s++; /* skip name */
- x = 0;
- if (*s == '-') {
- sgn = -1;
- s++;
- }
- while (isdigit(*s)) {
- x = 10 * x + toint(*s);
- s++;
- }
- off = x * SECS_PER_HOUR;
- if (*s == ':') {
- x = 0;
- s++;
- while (isdigit(*s)) {
- x = 10 * x + toint(*s);
- s++;
- }
- off += (x * SECS_PER_MIN);
- }
- if (isalpha(*s))
- *hasdst = 1;
- return sgn * off;
- }
-
- /*
- * Given a tm struct representing the local time, determine whether
- * DST is currently in effect. This should only be
- * called if it is known that the time zone indeed supports DST.
- *
- * FIXME: For now, assume that everyone follows the North American
- * time zone rules, all the time. This means daylight savings
- * time is assumed to be in effect from the first Sunday in April
- * to the last Sunday in October. Prior to 1987, the old rules
- * (last Sunday in April to last Sunday in Oct.) are used, even when
- * (as in 1974) they're not applicable. Sorry.
- *
- */
-
- static
- int indst(t)
- struct tm *t;
- {
- if (t->tm_mon == 3) { /* April */
- /* before 1987, see if there's another sunday in the month */
- if (t->tm_year < 87 && t->tm_wday + 30 - t->tm_mday < 7)
- return 1; /* no there isn't */
- /* after 1987, see if a sunday has happened yet */
- if (t->tm_wday - t->tm_mday < 0)
- return 1; /* yep */
- return 0;
- }
- if (t->tm_mon == 9) { /* October */
- if (t->tm_wday + 31 - t->tm_mday < 7)
- return 0; /* there are no more sundays */
- return 1;
- }
- /* Otherwise, see if it's a month between April and October exclusive */
- return (t->tm_mon > 3 && t->tm_mon < 9);
- }
-
- /* return difference between two time_t types -- ERS*/
-
-
- #ifdef __GNUC__
- double difftime(t1, t2)
- time_t t1, t2;
- {
- return (double) (t2 - t1);
- }
- #endif
-